#include "stdafx.h"

#include "hwinlocale.h"

namespace harlinn
{
    namespace windows
    {
        HWIN_EXPORT Locale::Data::Data()
            : referenceCount(1),name(nullptr)
        {}

        HWIN_EXPORT Locale::Data::Data(const wchar_t* theName)
            : referenceCount(1),name(nullptr)
        {
            if(theName)
            {
                size_t length = wcslen(theName);
                name = new wchar_t[length+1];
                wcscpy_s(name,length+1,theName);
            }
        }

        HWIN_EXPORT Locale::Data::Data(const String& theName)
            : referenceCount(1),name(nullptr)
        {
            if(theName)
            {
                size_t length = theName.length();
                name = new wchar_t[length+1];
                wcscpy_s(name,length+1,theName.c_str());
            }
        }

        HWIN_EXPORT Locale::Data::~Data()
        {
            if(name)
            {
                delete[] name;
            }
        }

        HWIN_EXPORT String Locale::Data::GetLocaleString(LCTYPE lctype) const
        {
            wchar_t buffer[512];
            lctype &= ~LOCALE_RETURN_NUMBER;
            auto length = GetLocaleInfoEx(name,lctype,buffer,512);
            if(length == 0)
            {
                auto lastError = GetLastError();
                if(lastError == ERROR_INSUFFICIENT_BUFFER)
                {
                    length = GetLocaleInfoEx(name,lctype,nullptr,0);
                    if(length == 0)
                    {
                        ThrowLastOSError();
                    }
                    else
                    {
                        String result;
                        result.SetLength(length-1);
                        length = GetLocaleInfoEx(name,lctype,result.c_str(),length-1);
                        return result;
                    }
                }
                else
                {
                    ThrowLastOSError();
                }
            }
            return String(buffer,String::size_type(length));
        }
        HWIN_EXPORT DWORD Locale::Data::GetLocaleValue(LCTYPE lctype) const
        {
            lctype |= LOCALE_RETURN_NUMBER;
            DWORD result = 0;
            if( GetLocaleInfoEx(name,lctype,(LPWSTR)&result,2) == 0)
            {
                ThrowLastOSError();
            }
            return result;
        }

        HWIN_EXPORT LOCALESIGNATURE Locale::Data::GetLocaleSignature() const
        {
            LOCALESIGNATURE result = {0,};
            if( GetLocaleInfoEx(name,LOCALE_FONTSIGNATURE,(LPWSTR)&result,sizeof(LOCALESIGNATURE)/2) == 0)
            {
                ThrowLastOSError();
            }
            return result;
        }


        HWIN_EXPORT DWORD Locale::Data::GetCalendarType() const
        {
            return GetLocaleValue(LOCALE_ICALENDARTYPE);
        }
        HWIN_EXPORT bool Locale::Data::GetCentury() const
        {
            return GetLocaleValue(LOCALE_ICENTURY) != 0;
        }
        HWIN_EXPORT DWORD Locale::Data::GetCountryRegionCode() const
        {
            return GetLocaleValue(LOCALE_ICOUNTRY);
        }
        HWIN_EXPORT DWORD Locale::Data::GetNumberOfFractionalDigitsForCurrency() const
        {
            return GetLocaleValue(LOCALE_ICURRDIGITS);
        }
        HWIN_EXPORT CurrencySymbolPosition Locale::Data::GetCurrencySymbolPosition() const
        {
            return CurrencySymbolPosition(GetLocaleValue(LOCALE_ICURRENCY));
        }
        HWIN_EXPORT DateFormat Locale::Data::GetDateFormat() const
        {
            return DateFormat(GetLocaleValue(LOCALE_IDATE));
        }
        HWIN_EXPORT bool Locale::Data::GetLeadingZeroForDays() const
        {
            return GetLocaleValue(LOCALE_IDAYLZERO) != 0;
        }
        HWIN_EXPORT DWORD Locale::Data::GetDefaultAnsiCodePage() const
        {
            return GetLocaleValue(LOCALE_IDEFAULTANSICODEPAGE);
        }
        HWIN_EXPORT DWORD Locale::Data::GetDefaultCodePage() const
        {
            return GetLocaleValue(LOCALE_IDEFAULTCODEPAGE);
        }
        HWIN_EXPORT DWORD Locale::Data::GetDefaultEBCDICCodePage() const
        {
            return GetLocaleValue(LOCALE_IDEFAULTEBCDICCODEPAGE);
        }
        HWIN_EXPORT DWORD Locale::Data::GetDefaultMacCodePage() const
        {
            return GetLocaleValue(LOCALE_IDEFAULTMACCODEPAGE);
        }
        HWIN_EXPORT DWORD Locale::Data::GetNumberOfFractionalDigits() const
        {
            return GetLocaleValue(LOCALE_IDIGITS);
        }
        HWIN_EXPORT DigitSubstitution Locale::Data::GetDigitSubstitution() const
        {
            return DigitSubstitution(GetLocaleValue(LOCALE_IDIGITSUBSTITUTION));
        }
        HWIN_EXPORT DWORD Locale::Data::GetFirstDayOfWeek() const
        {
            return GetLocaleValue(LOCALE_IFIRSTDAYOFWEEK);
        }
        HWIN_EXPORT DWORD Locale::Data::GetFirstWeekOfYear() const
        {
            return GetLocaleValue(LOCALE_IFIRSTWEEKOFYEAR);
        }
        HWIN_EXPORT int Locale::Data::GetGeoId() const
        {
            return GetLocaleValue(LOCALE_IGEOID);
        }
        HWIN_EXPORT DWORD Locale::Data::GetNumberOfFractionalDigitsForInternationalCurrency() const
        {
            return GetLocaleValue(LOCALE_IINTLCURRDIGITS);
        }
        HWIN_EXPORT DWORD Locale::Data::GetLanguageId() const
        {
            return GetLocaleValue(LOCALE_ILANGUAGE);
        }
        HWIN_EXPORT DateFormat Locale::Data::GetLongDateFormat() const
        {
            return DateFormat(GetLocaleValue(LOCALE_ILDATE));
        }
        HWIN_EXPORT bool Locale::Data::GetLeadingZeros() const
        {
            return GetLocaleValue(LOCALE_ILZERO) != 0;
        }
        HWIN_EXPORT MeasurementSystem Locale::Data::GetMeasurementSystem() const
        {
            return MeasurementSystem(GetLocaleValue(LOCALE_IMEASURE));
        }
        HWIN_EXPORT bool Locale::Data::GetLeadingZeroForMonths() const
        {
            return GetLocaleValue(LOCALE_IMONLZERO) != 0;
        }
        HWIN_EXPORT NegativePercentFormat Locale::Data::GetNegativePercentFormat() const
        {
            return NegativePercentFormat(GetLocaleValue(LOCALE_INEGATIVEPERCENT));
        }
        HWIN_EXPORT NegativeCurrencyFormat Locale::Data::GetNegativeCurrencyFormat() const
        {
            return NegativeCurrencyFormat(GetLocaleValue(LOCALE_INEGCURR));
        }
        HWIN_EXPORT NegativeNumberFormat Locale::Data::GetNegativeNumberFormat() const
        {
            return NegativeNumberFormat(GetLocaleValue(LOCALE_INEGNUMBER));
        }
        HWIN_EXPORT SignPosition Locale::Data::GetNegativeSignPosition() const
        {
            return SignPosition(GetLocaleValue(LOCALE_INEGSIGNPOSN));
        }
        HWIN_EXPORT bool Locale::Data::GetMonetarySymbolAndNegativeNumberSeparatedBySpace() const
        {
            return GetLocaleValue(LOCALE_INEGSEPBYSPACE) != 0;
        }
        HWIN_EXPORT bool Locale::Data::GetMonetarySymbolPrecedesNegativeAmount() const
        {
            return GetLocaleValue(LOCALE_INEGSYMPRECEDES) != 0;
        }
        HWIN_EXPORT DWORD Locale::Data::GetOptionalCalendarType() const
        {
            return GetLocaleValue(LOCALE_IOPTIONALCALENDAR);
        }
        HWIN_EXPORT DWORD Locale::Data::GetPaperSize() const
        {
            return GetLocaleValue(LOCALE_IPAPERSIZE);
        }
        HWIN_EXPORT PositivePercentFormat Locale::Data::GetPositivePercentFormat() const
        {
            return PositivePercentFormat(GetLocaleValue(LOCALE_IPOSITIVEPERCENT));
        }
        HWIN_EXPORT SignPosition Locale::Data::GetPositiveSignPosition() const
        {
            return SignPosition(GetLocaleValue(LOCALE_IPOSSIGNPOSN));
        }
        HWIN_EXPORT bool Locale::Data::GetMonetarySymbolAndNumberSeparatedBySpace() const
        {
            return GetLocaleValue(LOCALE_IPOSSEPBYSPACE) != 0;
        }
        HWIN_EXPORT bool Locale::Data::GetMonetarySymbolPrecedesAmount() const
        {
            return GetLocaleValue(LOCALE_IPOSSYMPRECEDES) != 0;
        }
        HWIN_EXPORT LocaleReadingLayout Locale::Data::GetLocaleReadingLayout() const
        {
            return LocaleReadingLayout(GetLocaleValue(LOCALE_IREADINGLAYOUT));
        }
        HWIN_EXPORT bool Locale::Data::Get24HourClock() const
        {
            return GetLocaleValue(LOCALE_ITIME) != 0;
        }
        HWIN_EXPORT bool Locale::Data::GetTimeMarkerAsPrefix() const
        {
            return GetLocaleValue(LOCALE_ITIMEMARKPOSN) != 0;
        }
        HWIN_EXPORT bool Locale::Data::GetLeadingZeroForHours() const
        {
            return GetLocaleValue(LOCALE_ITLZERO) != 0;
        }
        HWIN_EXPORT String Locale::Data::GetFirstTimeMarker() const
        {
            return GetLocaleString(LOCALE_S1159);
        }
        HWIN_EXPORT String Locale::Data::GetSecondTimeMarker() const
        {
            return GetLocaleString(LOCALE_S2359);
        }
        HWIN_EXPORT String Locale::Data::GetAbbreviatedCountryOrRegionName() const
        {
            return GetLocaleString(LOCALE_SABBREVCTRYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetAbbreviatedLanguageName() const
        {
            return GetLocaleString(LOCALE_SABBREVLANGNAME);
        }
        HWIN_EXPORT String Locale::Data::GetAbbreviatedMonthName(DWORD month) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SABBREVMONTHNAME1,
                LOCALE_SABBREVMONTHNAME2,
                LOCALE_SABBREVMONTHNAME3,
                LOCALE_SABBREVMONTHNAME4,
                LOCALE_SABBREVMONTHNAME5,
                LOCALE_SABBREVMONTHNAME6,
                LOCALE_SABBREVMONTHNAME7,
                LOCALE_SABBREVMONTHNAME8,
                LOCALE_SABBREVMONTHNAME9,
                LOCALE_SABBREVMONTHNAME10,
                LOCALE_SABBREVMONTHNAME11,
                LOCALE_SABBREVMONTHNAME12,
                LOCALE_SABBREVMONTHNAME13
            };
            return GetLocaleString(values[month]);
        }
        HWIN_EXPORT String Locale::Data::GetAbbreviatedDayName(DWORD day) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SABBREVDAYNAME1,
                LOCALE_SABBREVDAYNAME2,
                LOCALE_SABBREVDAYNAME3,
                LOCALE_SABBREVDAYNAME4,
                LOCALE_SABBREVDAYNAME5,
                LOCALE_SABBREVDAYNAME6,
                LOCALE_SABBREVDAYNAME7
            };
            return GetLocaleString(values[day]);
        }  
        HWIN_EXPORT String Locale::Data::GetMonthName(DWORD month) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SMONTHNAME1,
                LOCALE_SMONTHNAME2,
                LOCALE_SMONTHNAME3,
                LOCALE_SMONTHNAME4,
                LOCALE_SMONTHNAME5,
                LOCALE_SMONTHNAME6,
                LOCALE_SMONTHNAME7,
                LOCALE_SMONTHNAME8,
                LOCALE_SMONTHNAME9,
                LOCALE_SMONTHNAME10,
                LOCALE_SMONTHNAME11,
                LOCALE_SMONTHNAME12,
                LOCALE_SMONTHNAME13
            };
            return GetLocaleString(values[month]);
        }
        HWIN_EXPORT String Locale::Data::GetGenetiveMonthName(DWORD month) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SMONTHNAME1 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME2 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME3 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME4 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME5 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME6 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME7 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME8 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME9 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME10 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME11 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME12 | LOCALE_RETURN_GENITIVE_NAMES,
                LOCALE_SMONTHNAME13 | LOCALE_RETURN_GENITIVE_NAMES
            };
            return GetLocaleString(values[month]);
        }
        HWIN_EXPORT String Locale::Data::GetDayName(DWORD day) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SDAYNAME1,
                LOCALE_SDAYNAME2,
                LOCALE_SDAYNAME3,
                LOCALE_SDAYNAME4,
                LOCALE_SDAYNAME5,
                LOCALE_SDAYNAME6,
                LOCALE_SDAYNAME7
            };
            return GetLocaleString(values[day]);
        }
        HWIN_EXPORT String Locale::Data::GetShortDayName(DWORD day) const
        {
            const LCTYPE values[] = 
            {
                LOCALE_SSHORTESTDAYNAME1,
                LOCALE_SSHORTESTDAYNAME2,
                LOCALE_SSHORTESTDAYNAME3,
                LOCALE_SSHORTESTDAYNAME4,
                LOCALE_SSHORTESTDAYNAME5,
                LOCALE_SSHORTESTDAYNAME6,
                LOCALE_SSHORTESTDAYNAME7
            };
            return GetLocaleString(values[day]);
        }
        HWIN_EXPORT String Locale::Data::GetCurrencySymbol() const
        {
            return GetLocaleString(LOCALE_SCURRENCY);
        }
        HWIN_EXPORT String Locale::Data::GetDateSeparator() const
        {
            return GetLocaleString(LOCALE_SDATE);
        }
        HWIN_EXPORT String Locale::Data::GetDecimalSeparator() const
        {
            return GetLocaleString(LOCALE_SDECIMAL);
        }
        HWIN_EXPORT String Locale::Data::GetDurationFormat() const
        {
            return GetLocaleString(LOCALE_SDURATION);
        }
        HWIN_EXPORT String Locale::Data::GetEnglishCountryOrRegionName() const
        {
            return GetLocaleString(LOCALE_SENGLISHCOUNTRYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetEnglishCurrencyName() const
        {
            return GetLocaleString(LOCALE_SENGCURRNAME);
        }
        HWIN_EXPORT String Locale::Data::GetEnglishLanguageName() const
        {
            return GetLocaleString(LOCALE_SENGLISHLANGUAGENAME);
        }
        HWIN_EXPORT String Locale::Data::GetEnglishLocaleDisplayName() const
        {
            return GetLocaleString(LOCALE_SENGLISHDISPLAYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetDecimalGroups() const
        {
            return GetLocaleString(LOCALE_SGROUPING);
        }
        HWIN_EXPORT String Locale::Data::GetISO4217CurrencySymbol() const
        {
            return GetLocaleString(LOCALE_SINTLSYMBOL);
        }
        HWIN_EXPORT String Locale::Data::GetISO3166CountryName() const
        {
            return GetLocaleString(LOCALE_SISO3166CTRYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetISO3166ThreeLetterCode() const
        {
            return GetLocaleString(LOCALE_SISO3166CTRYNAME2);
        }
        HWIN_EXPORT String Locale::Data::GetISO639LanguageName() const
        {
            return GetLocaleString(LOCALE_SISO639LANGNAME);
        }
        HWIN_EXPORT String Locale::Data::GetISO639ThreeLetterLanguageName() const
        {
            return GetLocaleString(LOCALE_SISO639LANGNAME2);
        }
        HWIN_EXPORT String Locale::Data::GetKeyboardNames() const
        {
            return GetLocaleString(LOCALE_SKEYBOARDSTOINSTALL);
        }
        HWIN_EXPORT String Locale::Data::GetLanguageDisplayName() const
        {
            return GetLocaleString(LOCALE_SLANGDISPLAYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetListSeparator() const
        {
            return GetLocaleString(LOCALE_SLIST);
        }
        HWIN_EXPORT String Locale::Data::GetLocalizedCountryName() const
        {
            return GetLocaleString(LOCALE_SLOCALIZEDCOUNTRYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetLocalizedDisplayName() const
        {
            return GetLocaleString(LOCALE_SLOCALIZEDDISPLAYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetLocalizedLanguageName() const
        {
            return GetLocaleString(LOCALE_SLOCALIZEDLANGUAGENAME);
        }
        HWIN_EXPORT String Locale::Data::GetLongDateFormatString() const
        {
            return GetLocaleString(LOCALE_SLONGDATE);
        }
        HWIN_EXPORT String Locale::Data::GetMonetaryDecimalSeparator() const
        {
            return GetLocaleString(LOCALE_SMONDECIMALSEP);
        }
        HWIN_EXPORT String Locale::Data::GetMonetaryGrouping() const
        {
            return GetLocaleString(LOCALE_SMONGROUPING);
        }
        HWIN_EXPORT String Locale::Data::GetMonetaryThousandSeparator() const
        {
            return GetLocaleString(LOCALE_SMONTHOUSANDSEP);
        }
        HWIN_EXPORT String Locale::Data::GetMonthDayFormatString() const
        {
            return GetLocaleString(LOCALE_SMONTHDAY);
        }
        HWIN_EXPORT String Locale::Data::GetName() const
        {
            return GetLocaleString(LOCALE_SNAME);
        }
        HWIN_EXPORT String Locale::Data::GetNan() const
        {
            return GetLocaleString(LOCALE_SNAN);
        }
        HWIN_EXPORT String Locale::Data::GetNativeCountryName() const
        {
            return GetLocaleString(LOCALE_SNATIVECOUNTRYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetNativeCurrencyName() const
        {
            return GetLocaleString(LOCALE_SNATIVECURRNAME);
        }
        HWIN_EXPORT String Locale::Data::GetNativeDigits() const
        {
            return GetLocaleString(LOCALE_SNATIVEDIGITS);
        }
        HWIN_EXPORT String Locale::Data::GetNativeLanguageName() const
        {
            return GetLocaleString(LOCALE_SNATIVELANGUAGENAME);
        }
        HWIN_EXPORT String Locale::Data::GetNativeDisplayName() const
        {
            return GetLocaleString(LOCALE_SNATIVEDISPLAYNAME);
        }
        HWIN_EXPORT String Locale::Data::GetNegativeSign() const
        {
            return GetLocaleString(LOCALE_SNEGATIVESIGN);
        }
        HWIN_EXPORT String Locale::Data::GetNegativeInfinity() const
        {
            return GetLocaleString(LOCALE_SNEGINFINITY);
        }
        HWIN_EXPORT String Locale::Data::GetOpenTypeLanguageTag() const
        {
            return GetLocaleString(LOCALE_SOPENTYPELANGUAGETAG);
        }
        HWIN_EXPORT String Locale::Data::GetLocaleNameForSorting() const
        {
            return GetLocaleString(LOCALE_SSORTNAME);
        }
        HWIN_EXPORT String Locale::Data::GetFallbackLocale() const
        {
            return GetLocaleString(LOCALE_SPARENT);
        }
        HWIN_EXPORT String Locale::Data::GetPercent() const
        {
            return GetLocaleString(LOCALE_SPERCENT);
        }
        HWIN_EXPORT String Locale::Data::GetPermille() const
        {
            return GetLocaleString(LOCALE_SPERMILLE);
        }
        HWIN_EXPORT String Locale::Data::GetPositiveInfinity() const
        {
            return GetLocaleString(LOCALE_SPOSINFINITY);
        }
        HWIN_EXPORT String Locale::Data::GetPositiveSign() const
        {
            return GetLocaleString(LOCALE_SPOSITIVESIGN);
        }
        HWIN_EXPORT String Locale::Data::GetScripts() const
        {
            return GetLocaleString(LOCALE_SSCRIPTS);
        }
        HWIN_EXPORT String Locale::Data::GetShortDateFormatString() const
        {
            return GetLocaleString(LOCALE_SSHORTDATE);
        }
        HWIN_EXPORT String Locale::Data::GetShortTimeFormatString() const
        {
            return GetLocaleString(LOCALE_SSHORTTIME);
        }
        HWIN_EXPORT String Locale::Data::GetLongTimeFormatString() const
        {
            return GetLocaleString(LOCALE_STIMEFORMAT);
        }
        HWIN_EXPORT String Locale::Data::GetThousandSeparator() const
        {
            return GetLocaleString(LOCALE_STHOUSAND);
        }
        HWIN_EXPORT String Locale::Data::GetYearMonthFormatString() const
        {
            return GetLocaleString(LOCALE_SYEARMONTH);
        }


        HWIN_EXPORT Locale Locale::Invariant(LOCALE_NAME_INVARIANT);
        HWIN_EXPORT Locale Locale::System(LOCALE_NAME_SYSTEM_DEFAULT);
        HWIN_EXPORT Locale Locale::User(LOCALE_NAME_USER_DEFAULT);


        
    };
};